﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Xml;

using GMap.NET.CacheProviders;
using GMap.NET.Projections;
using GMap.NET.Internals;

using FLEN_Sim.config;

namespace GMap.NET.RouteProviders
{
    /// <summary>
    /// Liefer eine Route zwischen zwei Punkten.
    /// 
    /// Autor: Viktor Bergmann - http://greatmaps.codeplex.com/SourceControl/network/Forks/ViktorBergman/viktorbergman
    /// </summary>
    public class YouRouteProvider : IRouteProvider
    {
        public string ApplicationKey { get; set; }

        MapRoute IRouteProvider.GetRouteBetweenPoints(PointLatLng start, PointLatLng end, bool avoidHighways, int Zoom)
        {

            List<PointLatLng> points = GetRoutePoints(MakeUrl(start, end, "motorcar"));

            MapRoute route = new MapRoute(points, "Driving");
            return route;

        }

        MapRoute IRouteProvider.GetRouteBetweenPoints(string start, string end, bool avoidHighways, int Zoom)
        {
            return null;
        }

        MapRoute IRouteProvider.GetWalkingRouteBetweenPoints(PointLatLng start, PointLatLng end, int Zoom)
        {
            List<PointLatLng> points = GetRoutePoints(MakeUrl(start, end, "foot"));

            MapRoute route = new MapRoute(points, "Walking");
            return route;

        }

        MapRoute IRouteProvider.GetWalkingRouteBetweenPoints(string start, string end, int Zoom)
        {
            return null;
        }

        internal string MakeUrl(PointLatLng start, PointLatLng end, string travelType)
        {
            return String.Format("http://www.yournavigation.org/api/1.0/gosmore.php?format=kml&flat={0}&flon={1}&tlat={2}&tlon={3}&v={4}&fast=1&layer=mapnik", start.Lat.ToString().Replace(",", "."), start.Lng.ToString().Replace(",", "."), end.Lat.ToString().Replace(",", "."), end.Lng.ToString().Replace(",", "."), travelType);
        }

        internal List<PointLatLng> GetRoutePoints(string url)
        {
            List<PointLatLng> points = new List<PointLatLng>();
            try
            {

                //string route = GMaps.Instance.UseRouteCache ? Cache.Instance.GetRouteFromCache(url) : string.Empty;
                string route = string.Empty;

                if (string.IsNullOrEmpty(route))
                {
                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                    request.UserAgent = Config.USERAGENT;
                    request.Headers.Add(HttpRequestHeader.From, Config.EMAIL);
                    request.Headers.Add("X-Client", "FLEN-Sim; http://code.google.com/p/flen-sim/; s.markert87@googlemail.com");
                    request.ServicePoint.ConnectionLimit = 50;
                    if (GMaps.Instance.Proxy != null)
                    {
                        request.Proxy = GMaps.Instance.Proxy;
                        request.PreAuthenticate = true;
                    }
                    else
                    {
#if !PocketPC
                        request.Proxy = WebRequest.DefaultWebProxy;
#endif
                    }

                    request.UserAgent = GMaps.Instance.UserAgent;
                    request.Timeout = GMaps.Instance.Timeout;
                    request.ReadWriteTimeout = GMaps.Instance.Timeout * 6;
                    request.KeepAlive = false;

                    using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
                    {
                        using (Stream responseStream = response.GetResponseStream())
                        {
                            using (StreamReader read = new StreamReader(responseStream))
                            {
                                route = read.ReadToEnd();
                            }
                        }
                    }

                    // cache routing
                    //if (GMaps.Instance.UseRouteCache)
                    //{
                    //    Cache.Instance.CacheRoute(url, route);
                    //}

                    if (route != null)
                    {
                        points = GetPointsFromKml(route);
                    }

                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }

            return points;
        }

        private List<PointLatLng> GetPointsFromKml(string content)
        {
            try
            {
                XmlDocument xmldoc = new XmlDocument();
                xmldoc.LoadXml(content);
                System.Xml.XmlNamespaceManager xmlnsManager = new System.Xml.XmlNamespaceManager(xmldoc.NameTable);
                xmlnsManager.AddNamespace("sm", "http://earth.google.com/kml/2.0");

                List<PointLatLng> points = new List<PointLatLng>();

                ///Folder/Placemark/LineString/coordinates
                var coordNode = xmldoc.SelectSingleNode("/sm:kml/sm:Document/sm:Folder/sm:Placemark/sm:LineString/sm:coordinates", xmlnsManager);

                string[] coordinates = coordNode.InnerText.Split(new string[] { "\n" }, StringSplitOptions.None);

                foreach (string coordinate in coordinates)
                {
                    if (coordinate != string.Empty)
                    {
                        string[] XY = coordinate.Split(new string[] { "," }, StringSplitOptions.None);
                        if (XY.Length == 2)
                        {
                            double lat = double.Parse(XY[1].Replace(".", ","));
                            double lng = double.Parse(XY[0].Replace(".", ","));
                            points.Add(new PointLatLng(lat, lng));
                        }
                    }
                }

                return points;
            }
            catch (Exception)
            {
                return null;
            }
        }

    }
}
